二叉树中序遍历非递归算法

我们知道,在深度搜索遍历的过程中,之所以要用递归或者是用非递归的栈方式,参考二叉树非递归中序遍历,都是因为其他的方式没法记录当前节点的parent,而如果在每个节点的结构里面加个parent 分量显然是不现实的,那么Morris是怎么解决这一问题的呢?好吧,他用得很巧妙,实际上是用叶子节点的空指针来记录当前节点的位置,然后一旦遍历到了叶子节点,发现叶子节点的右指针指向的是当前节点,那么就认为以当前节点的左子树已经遍历完成。Morris 遍历正是利用了线索二叉树 的思想。

以inorder为例,初始化当前节点为root,它的遍历规则如下:

  • 如果当前节点为空,程序退出。
  • 如果当前节点非空,
    • 如果当前节点的左儿子为空,那么输出当前节点,当前节点重置为当前节点的右儿子。

    • 如果当前节点的左儿子非空,找到当前节点左子树的最右叶子节点(此时最右节点的右儿子有两种情况,一种是指向当前节点,一种是为空,你也许感到奇怪,右节点的右儿子怎么可能非空,注意,这里的最右叶子节点只带的是原树中的最右叶子节点。),若其最右叶子节点为空,令其指向当前节点,将当前节点重置为其左儿子,若其最右节点指向当前节点,输出当前节点,将当前节点重置为当前节点的右儿子,并恢复树结构,即将最右节点的右节点再次设置为NULL
      #include<stdio.h>
      02 #include<stdlib.h>
      03  
      04 struct tNode
      05 {
      06    int data;
      07    struct tNode* left;
      08    struct tNode* right;
      09 };
      10  
      11 void MorrisTraversal(struct tNode *root)
      12 {
      13   struct tNode *current,*pre;
      14  
      15   if(root == NULL)
      16      return;
      17  
      18   current = root;
      19   while(current != NULL)
      20   {                
      21     if(current->left == NULL)
      22     {
      23       printf(" %d ", current->data);
      24       current = current->right;     
      25     }   
      26     else
      27     {
      28       /* 找到current的前驱节点 */
      29       pre = current->left;
      30       while(pre->right != NULL && pre->right != current)
      31         pre = pre->right;
      32  
      33       /* 将current节点作为其前驱节点的右孩子 */
      34       if(pre->right == NULL)
      35       {
      36         pre->right = current;
      37         current = current->left;
      38       }
      39  
      40       /* 恢复树的原有结构,更改right 指针 */  
      41       else
      42       {
      43         pre->right = NULL;
      44         printf(" %d ",current->data);
      45         current = current->right;     
      46       /* End of if condition pre->right == NULL */
      47     /* End of if condition current->left == NULL*/
      48   /* End of while */
      49 }
      50  
      51 struct tNode* newtNode(int data)
      52 {
      53   struct tNode* tNode = (struct tNode*)
      54                        malloc(sizeof(struct tNode));
      55   tNode->data = data;
      56   tNode->left = NULL;
      57   tNode->right = NULL;
      58  
      59   return(tNode);
      60 }
      61  
      62 /* 测试*/
      63 int main()
      64 {
      65  
      66   /* 构建树结构如下:
      67             1
      68           /   \
      69         2      3
      70       /  \
      71     4     5
      72   */
      73   struct tNode *root = newtNode(1);
      74   root->left        = newtNode(2);
      75   root->right       = newtNode(3);
      76   root->left->left  = newtNode(4);
      77   root->left->right = newtNode(5);
      78  
      79   MorrisTraversal(root);
      80    return 0;
      81 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值